package com.eshop.modules.activity.service.impl;

import java.lang.invoke.SerializedLambda;
import java.io.IOException;
import com.eshop.utils.FileUtil;
import javax.servlet.http.HttpServletResponse;
import com.eshop.common.utils.QueryHelpPlus;
import java.util.LinkedHashMap;
import com.eshop.modules.user.domain.ShopUser;
import com.eshop.modules.activity.service.dto.StoreCouponUserDto;
import com.github.pagehelper.PageInfo;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.activity.service.dto.StoreCouponUserQueryCriteria;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.HashSet;
import java.util.Collection;
import com.eshop.enums.CouponGetEnum;
import cn.hutool.core.date.DateUtil;
import com.eshop.api.EshopException;
import java.io.Serializable;
import com.eshop.modules.activity.domain.StoreCoupon;
import java.util.ArrayList;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.eshop.modules.activity.vo.StoreCouponUserQueryVo;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import cn.hutool.core.util.NumberUtil;
import java.math.BigDecimal;
import com.eshop.modules.cart.vo.StoreCartQueryVo;
import com.eshop.modules.activity.vo.StoreCouponUserVo;
import java.util.List;
import com.eshop.enums.CouponEnum;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.eshop.modules.cart.service.StoreCartService;
import com.eshop.modules.activity.service.StoreCouponService;
import com.eshop.modules.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import com.eshop.dozer.service.IGenerator;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import com.eshop.modules.activity.service.StoreCouponUserService;
import com.eshop.modules.activity.domain.StoreCouponUser;
import com.eshop.modules.activity.service.mapper.StoreCouponUserMapper;
import com.eshop.common.service.impl.BaseServiceImpl;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = { Exception.class })
public class StoreCouponUserServiceImpl extends BaseServiceImpl<StoreCouponUserMapper, StoreCouponUser> implements StoreCouponUserService
{
    @Autowired
    private IGenerator generator;
    @Autowired
    private StoreCouponUserMapper storeCouponUserMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private StoreCouponService storeCouponService;
    @Autowired
    private StoreCartService storeCartService;
    
    public int getUserValidCouponCount(final Long uid) {
        //先更新一下已经过期了的优惠券
        this.checkInvalidCoupon();
        //然后再获取有效优惠券数量
        return ((this.lambdaQuery().eq(StoreCouponUser::getStatus, CouponEnum.STATUS_0.getValue())).eq(StoreCouponUser::getUid, uid)).count();
    }
    
    public List<StoreCouponUserVo> beUsableCouponList(final Long uid, final String cartIds) {
        final Map<String, Object> cartGroup = this.storeCartService.getUserProductCartList(uid, cartIds, 1);
        final List<StoreCartQueryVo> cartInfo = (List<StoreCartQueryVo>) cartGroup.get("valid");
        BigDecimal sumPrice = BigDecimal.ZERO;
        for (final StoreCartQueryVo storeCart : cartInfo) {
            sumPrice = NumberUtil.add((Number)sumPrice, (Number)NumberUtil.mul((Number)storeCart.getCartNum(), (Number)storeCart.getTruePrice()));
        }
        final List<String> productIds = cartInfo.stream().map(StoreCartQueryVo::getProductId).map(Object::toString).collect(Collectors.toList());
        return this.getUsableCouponList(uid, sumPrice.doubleValue(), productIds);
    }
    
    public List<StoreCouponUserVo> getUsableCouponList(final Long uid, final double price, final List<String> productIds) {
        final Date now = new Date();
        final List<StoreCouponUserVo> storeCouponUsers = this.storeCouponUserMapper.selectCouponList(now, price, uid);
        return storeCouponUsers.stream().filter(coupon -> CouponEnum.TYPE_2.getValue().equals(coupon.getType()) || CouponEnum.TYPE_0.getValue().equals(coupon.getType()) || (CouponEnum.TYPE_1.getValue().equals(coupon.getType()) && this.isSame(Arrays.asList(coupon.getProductId().split(",")), productIds))).collect(Collectors.toList());
    }
    
    public StoreCouponUser getCoupon(final Integer id, final Long uid) {
        return (StoreCouponUser)((((this.lambdaQuery().eq(StoreCouponUser::getIsFail, CouponEnum.FALI_0.getValue())).eq(StoreCouponUser::getStatus, CouponEnum.STATUS_0.getValue())).eq(StoreCouponUser::getUid, uid)).eq(StoreCouponUser::getId, id)).one();
    }
    
    public void useCoupon(final int id) {
        final StoreCouponUser couponUser = new StoreCouponUser();
        couponUser.setId((long)id);
        couponUser.setStatus(1);
        couponUser.setUseTime(new Date());
        this.storeCouponUserMapper.updateById(couponUser);
    }
    
    public List<StoreCouponUserQueryVo> getUserCoupon(final Long uid) {
        final List<StoreCouponUser> storeCouponUsers = (List<StoreCouponUser>)this.storeCouponUserMapper.selectList(Wrappers.<StoreCouponUser>lambdaQuery().eq(StoreCouponUser::getUid, uid));
        final List<StoreCouponUserQueryVo> storeCouponUserQueryVoList = new ArrayList<StoreCouponUserQueryVo>();
        final long nowTime = System.currentTimeMillis();
        for (final StoreCouponUser couponUser : storeCouponUsers) {
            final StoreCouponUserQueryVo queryVo = (StoreCouponUserQueryVo)this.generator.convert(couponUser, (Class)StoreCouponUserQueryVo.class);
            if (couponUser.getIsFail() == 1) {
                queryVo.set_type(CouponEnum.USE_0.getValue());
                queryVo.set_msg("已失效");
            }
            else if (couponUser.getStatus() == 1) {
                queryVo.set_type(CouponEnum.USE_0.getValue());
                queryVo.set_msg("已使用");
            }
            else if (couponUser.getStatus() == 2) {
                queryVo.set_type(CouponEnum.USE_0.getValue());
                queryVo.set_msg("已过期");
            }
            else if (couponUser.getCreateTime().getTime() > nowTime || couponUser.getEndTime().getTime() < nowTime) {
                queryVo.set_type(CouponEnum.USE_0.getValue());
                queryVo.set_msg("已过期");
            }
            else {
                queryVo.set_type(CouponEnum.USE_1.getValue());
                queryVo.set_msg("可使用");
            }
            storeCouponUserQueryVoList.add(queryVo);
        }
        return storeCouponUserQueryVoList;
    }
    
    public void addUserCoupon(final Long uid, final Integer cid) {
        final StoreCoupon storeCoupon = (StoreCoupon)this.storeCouponService.getById((Serializable)cid);
        if (storeCoupon == null) {
            throw new EshopException("优惠劵不存在");
        }
        final Date now = new Date();
        final Date endTime = (Date)DateUtil.offsetDay(now, (int)storeCoupon.getCouponTime());
        final StoreCouponUser storeCouponUser = StoreCouponUser.builder().cid(storeCoupon.getId()).uid(uid).couponPrice(storeCoupon.getCouponPrice()).couponTitle(storeCoupon.getTitle()).useMinPrice(storeCoupon.getUseMinPrice()).endTime(endTime).type(CouponGetEnum.GET.getValue()).build();
        this.save(storeCouponUser);
    }
    
    private boolean isSame(List<String> list1, List<String> list2) {
        if (list2.isEmpty()) {
            return true;
        }
        list1 = new ArrayList<String>(list1);
        list2 = new ArrayList<String>(list2);
        list1.addAll(list2);
        final int total = list1.size();
        final List<String> newList = new ArrayList<String>(new HashSet<String>(list1));
        final int newTotal = newList.size();
        return total > newTotal;
    }
    
    private void checkInvalidCoupon() {
        //将没有使用过的且已经过期的优惠券全部修改状态为2，即为不可使用
        final Date nowTime = new Date();
        final LambdaQueryWrapper<StoreCouponUser> wrapper = (LambdaQueryWrapper<StoreCouponUser>)new LambdaQueryWrapper();
        (wrapper.lt(StoreCouponUser::getEndTime, nowTime)).eq(StoreCouponUser::getStatus, CouponEnum.STATUS_0.getValue());
        final StoreCouponUser couponUser = new StoreCouponUser();
        couponUser.setStatus(CouponEnum.STATUS_2.getValue());
        this.storeCouponUserMapper.update(couponUser, (Wrapper)wrapper);
    }
    
    public Map<String, Object> queryAll(final StoreCouponUserQueryCriteria criteria, final Pageable pageable) {
        this.getPage(pageable);
        final PageInfo<StoreCouponUser> page = (PageInfo<StoreCouponUser>)new PageInfo((List)this.queryAll(criteria));
        final List<StoreCouponUserDto> storeOrderDTOS = (List<StoreCouponUserDto>)this.generator.convert(page.getList(), (Class)StoreCouponUserDto.class);
        for (final StoreCouponUserDto couponUserDTO : storeOrderDTOS) {
            couponUserDTO.setNickname(((ShopUser)this.userService.getOne(Wrappers.<ShopUser>lambdaQuery().eq(ShopUser::getUid, couponUserDTO.getUid()))).getNickname());
        }
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        map.put("content", storeOrderDTOS);
        map.put("totalElements", page.getTotal());
        return map;
    }
    
    public List<StoreCouponUser> queryAll(final StoreCouponUserQueryCriteria criteria) {
        return (List<StoreCouponUser>)((StoreCouponUserMapper)this.baseMapper).selectList((Wrapper)QueryHelpPlus.getPredicate(StoreCouponUser.class, criteria));
    }
    
    public void download(final List<StoreCouponUserDto> all, final HttpServletResponse response) throws IOException {
        final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (final StoreCouponUserDto yxStoreCouponUser : all) {
            final Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("兑换的项目id", yxStoreCouponUser.getCid());
            map.put("优惠券所属用户", yxStoreCouponUser.getUid());
            map.put("优惠券名称", yxStoreCouponUser.getCouponTitle());
            map.put("优惠券的面值", yxStoreCouponUser.getCouponPrice());
            map.put("最低消费多少金额可用优惠券", yxStoreCouponUser.getUseMinPrice());
            map.put("优惠券创建时间", yxStoreCouponUser.getAddTime());
            map.put("优惠券结束时间", yxStoreCouponUser.getEndTime());
            map.put("使用时间", yxStoreCouponUser.getUseTime());
            map.put("获取方式", yxStoreCouponUser.getType());
            map.put("状态（0：未使用，1：已使用, 2:已过期）", yxStoreCouponUser.getStatus());
            map.put("是否有效", yxStoreCouponUser.getIsFail());
            list.add(map);
        }
        FileUtil.downloadExcel((List)list, response);
    }
}
